Skip to content

chore(lint): shellcheck the launchctl test mock - #124

Merged
django23 merged 1 commit into
mainfrom
chore/lint-launchctl-mock
Jul 29, 2026
Merged

chore(lint): shellcheck the launchctl test mock#124
django23 merged 1 commit into
mainfrom
chore/lint-launchctl-mock

Conversation

@django23

Copy link
Copy Markdown
Collaborator

The tests/bin/launchctl mock added in #123 wasn't added to the lint target's file list. Every other script under tests/bin/ is linted.

It is already clean — this just stops it drifting.

Every other script under tests/bin/ is linted; the launchctl mock added
alongside `asimov doctor` was missed.
@django23
django23 merged commit 1b9c325 into main Jul 29, 2026
5 checks passed
@django23
django23 deleted the chore/lint-launchctl-mock branch July 29, 2026 12:34
lunaluxie pushed a commit to lunaluxie/asimov that referenced this pull request Jul 30, 2026
Every other script under tests/bin/ is linted; the launchctl mock added
alongside `asimov doctor` was missed.

Co-authored-by: django23 <827397+django23@users.noreply.github.com>
django23 added a commit that referenced this pull request Jul 30, 2026
* feat(config): add configuration option for skip search paths

* docs(readme): Update readme to describe the skip_paths configuration

* docs(readme): add optional directory argument to CLI summary.

update CLI usage summary to include optional directory argument mirroring actual CLI help text.

* feat(tests): add [skip_paths] config behavior test

* docs(changelog): add [skip_paths] config option to changelog

* feat(config): scan directories beyond home via [scan] extra

Add a [scan] section to ~/.config/asimov/config with one `extra =` line per
additional root; each is scanned on every run alongside the home directory.

- Resolve all roots into a single ASIMOV_SCAN_DIRS array; every consumer
  (Spotlight cache, path cache scoping, mdfind discovery, find traversal) loops
  over it instead of a lone ASIMOV_SCAN_DIR
- A positional CLI argument still overrides everything (scans only that path)
- Configured dirs that don't exist are warned about (honoring --quiet) and
  skipped, so an unmounted volume doesn't abort the run
- Nested/duplicate roots are pruned so no tree is traversed twice

Closes #108

* docs: prepare v0.9.0 stable release

- CHANGELOG: promote [scan] and Go-cache entries into [0.9.0], date 2026-07-26
- README: Install split into Homebrew (homebrew-core) + curl; document [scan];
  drop the retired django23 tap; note the pending homebrew-core 0.3.0→0.9.0 bump
- UPGRADING: point install commands at the stable curl one-liner
- CONTRIBUTING: Homebrew distribution is homebrew-core; mark tap targets legacy
- Makefile: verify-release falls back to `brew install asimov` (core), not the tap

* chore(release): bump version to 0.10.0

Stable release carrying the v0.9.0-beta fixes plus the new [scan] multi-scan
feature. A new feature is a minor bump under semver, so the beta line's 0.9.0
becomes 0.10.0 for stable (there was no 0.9.0 stable).

* docs(readme): correct homebrew-core version note (version-agnostic)

* docs,build: homebrew-core autobumps; drop retired tap tooling

- Makefile: remove bump-formula/ship-formula/TAP_DIR (tap archived); release
  target points at homebrew-core autobump; verify-release notes the ~3h lag
- README: homebrew note is now version-agnostic (formula auto-updates)
- CONTRIBUTING: release flow drops the tap steps; document that asimov is on
  Homebrew's autobump list (version PRs are automatic; only metadata needs a
  manual PR)

* docs(contributing): add concise release pipeline overview (PR → release → brew)

* chore: gitignore docs/triage (local maintainer notes)

* ci: test across both macOS bash versions in a parallel matrix

asimov starts with #!/usr/bin/env bash, so it runs under whichever bash comes
first on PATH. On macOS that is one of two very different things: /bin/bash,
still 3.2 because Apple froze it at the last GPLv2 release and what most users
get, or a 5.x build from Homebrew, which is what a development machine usually
has. They disagree on array and IFS semantics, so until now a change could pass
`make check` locally and CI and still be broken for users.

CI now runs os × bash (4 cells, all concurrent, fail-fast off so one failing
combination cannot hide the others). ShellCheck moves into its own job because it
is interpreter-independent and only needs to run once; it runs alongside the test
cells rather than four times over. A concurrency group cancels an in-flight run
when the same ref is pushed again.

Locally, `make test-system-bash` runs the suite under 3.2, and
`make test BASH_BIN=<path>` pins any interpreter. Both go through the new
scripts/test.sh, which sets ASIMOV_TEST_BASH; the Bats helper then launches
asimov with that interpreter explicitly, so Bats itself keeps running under its
own bash rather than being dragged down to 3.2 by a PATH shim.

`make test BATS_JOBS=N` runs tests concurrently (needs GNU parallel). Each test
already gets its own temp HOME in setup(), so there is no shared state.

* docs(readme): add a "What Asimov doesn't do" section

Covers the three most common misconceptions: Asimov sets Time Machine
exclusions only, it does not hide directories from Spotlight, and it does
not shrink backups that already exist. Adds a short verification recipe
for the "my node_modules is still in Time Machine" case.

Refs #90, #45

* feat(prune): add an asimov prune subcommand

Reports Time Machine exclusions whose directory no longer exists and
compacts Asimov's own path cache.

The premise of #38 turned out not to hold for Asimov's own work: every
version in git history calls `tmutil addexclusion PATH`, which stores the
exclusion as an extended attribute on the directory, so deleting the
directory deletes the exclusion with it. Nothing is left behind.

Staleness lives in the other mechanism — `tmutil addexclusion -p`, which
records the path in Time Machine's system preferences and survives the
directory forever. Asimov has never written that list, but other tools and
manual commands do, and nothing surfaces the leftovers.

So prune reports rather than removes: the entries are system-wide and not
ours to delete. It prints the `sudo tmutil removeexclusion -p` command
instead. The only file it writes is Asimov's own cache.

Closes #38

* fix(cache): survive an unreadable or unwritable cache

The cache under ~/.cache/asimov is an optimisation, but nothing treated it
as optional. A bare `cat` on an unreadable state file failed under
`set -Eeu -o pipefail` and aborted the run immediately, printing nothing
but "Permission denied" — no context, no fix, exit 1.

The cause was Asimov itself. ensure_cache_dir chowned the cache directory
to the console user when running as root, but the state files were created
*after* that chown, so every `sudo asimov` left root-owned files behind and
broke the next run as the user.

Guard every cache read and write behind cache_readable/cache_writable, warn
once naming the reset command, and carry on without the cache. Create the
state files before the chown so appends — which never change an existing
file's owner — keep them owned by the user who has to read them next.

Closes #122

* feat(doctor): add an asimov doctor subcommand

Checks the install rather than the projects: which asimov the shell
actually runs, whether a schedule is installed and loaded, whether the
cache is readable and writable, whether the config parses, and whether
tmutil can read exclusions at all. Exits 1 if it finds anything.

Two rules keep it safe to run part-way through a migration. It never
writes — fixes are printed, not applied. And it never executes another
asimov binary it finds: v0.3.0 parses no arguments at all, so running it
to ask its version would start a real scan, so versions are read out of
the file instead.

The test helper now strips any real asimov install from PATH, since doctor
inspects PATH and would otherwise report a different result per machine.

Refs #122

* docs: cover upgrading from v0.3.0 and document doctor

v0.3.0 is the version most people have, and it parses no arguments at all:
`asimov --version` and `asimov doctor` are both ignored and it goes
straight to scanning. So the upgrade notes lead with a version check that
reads the file instead of running it, and put `asimov doctor` last, after
the new binary is in place.

Also documents the three leftovers that outlive a v0.3.0 install — the
LaunchAgent, the old cellar, and a root-owned cache — and that Asimov is a
one-shot scan, not a daemon, so an empty `ps aux | grep asimov` after
`brew services start` is expected.

Refs #122

* chore(lint): shellcheck the launchctl test mock (#124)

Every other script under tests/bin/ is linted; the launchctl mock added
alongside `asimov doctor` was missed.

Co-authored-by: django23 <827397+django23@users.noreply.github.com>

* docs: release 0.11.0 (#125)

* test(doctor): derive the expected version from the script

The version assertion hardcoded 0.10.0, so it failed the moment the
release bump landed. Read it from `asimov --version` instead.

* docs: release 0.11.0

---------

Co-authored-by: django23 <827397+django23@users.noreply.github.com>

* feat(config): fold [skip_paths] into ASIMOV_SKIP_PATHS and teach doctor about it

Follow-up to the [skip_paths] work: append the configured paths to
ASIMOV_SKIP_PATHS at definition time instead of merging them into a local
array in each consumer, so the find expression and the Spotlight pass stay
in step, add the section to the doctor config validator (it reported
[skip_paths] as an unknown section), and cover both in tests.

The behaviour test passed an absolute path to create_project, which prefixes
$HOME - so the project was built outside the skipped directory and the test
passed for the wrong reason. Fixed, plus a control case that fails without
the config, a multi-entry case, and one proving [fixed_dirs] still wins
inside a skipped path.

---------

Co-authored-by: django23 <827397+django23@users.noreply.github.com>
Co-authored-by: Django E <djangoboy@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant